package com.edgar.fileupload.library;

import android.text.TextUtils;

import com.edgar.baselibrary.utils.IOUtils;
import com.edgar.baselibrary.utils.ThreadUtils;
import com.edgar.loglib.LogUtils;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 文件上传任务类,负责网络通信.
 */
public class FileUploadTask implements Runnable{

	private static final String TAG = FileUploadTask.class.getSimpleName();
	private static final String CONTENT_TYPE = "multipart/form-data";
	private static final String LINE_BREAK = "\r\n";
	private static final String CENTER_LINE = "--";
	private String mBoundary = UUID.randomUUID().toString();
	private UploadRequest mUploadRequest;

	public FileUploadTask(UploadRequest uploadRequest) {
		this.mUploadRequest = uploadRequest;
	}

	@Override
	public void run() {
		DataOutputStream dos = null;
		InputStream is = null;
		HttpURLConnection httpURLConnection = null;
		try {
			URL url = new URL(mUploadRequest.url);
			httpURLConnection = (HttpURLConnection) url.openConnection();
			httpURLConnection.setRequestMethod("POST");
			setHeader(httpURLConnection);
			OutputStream outputSteam = httpURLConnection.getOutputStream();
			dos = new DataOutputStream(outputSteam);
			List<File> files = mUploadRequest.uploadFiles;
			if(files != null && files.size() > 0){
				for (File uploadFile : files){
					if(uploadFile.exists()){
						transferFile(dos,uploadFile);
					}
				}
			}
			dos.flush();
			//传输完成,读取服务器的响应信息
			final String result = processResponse(httpURLConnection);
			if(!TextUtils.isEmpty(result)){
				ThreadUtils.runMainThread(new Runnable() {
					@Override
					public void run() {
						OnUploadListener listener = mUploadRequest.listener;
						if (listener != null) {
							listener.onResponse(result);
						}
					}
				});
			}
		} catch (MalformedURLException e) {
			LogUtils.e("Main", "MalformedUrlError:" + e.getMessage());
		} catch (IOException e) {
			LogUtils.e("Main","IoError:"+e.getMessage());
		} finally {
			IOUtils.closeQuietly(dos);
			IOUtils.closeQuietly(is);
			if(httpURLConnection != null){
				httpURLConnection.disconnect();
			}
		}
	}

	private String processResponse(HttpURLConnection httpURLConnection)throws IOException{
		if(httpURLConnection.getErrorStream() != null){
			throw new IOException("File upload error");
		}
		int responseCode = httpURLConnection.getResponseCode();
		if(responseCode == HttpURLConnection.HTTP_OK){
			//如果响应码是200,需要读取服务器响应的结果
			return parseResponse(httpURLConnection.getInputStream());
		} else {
			throw new IOException("Response code:"+responseCode);
		}
	}

	private String parseResponse(InputStream inputStream){
		return IOUtils.readString(inputStream);
	}

	/**
	 * transfer file.
	 */
	private void transferFile(OutputStream outputStream,File file)throws IOException{
		FileInputStream fileInputStream = null;
		try {
			//write start body and file name.
			outputStream.write(buildStartData(file.getName()).getBytes());
			fileInputStream = new FileInputStream(file);
			IOUtils.writeStream(fileInputStream, outputStream);
			outputStream.write(LINE_BREAK.getBytes());
			byte[] end_data = (CENTER_LINE + mBoundary + CENTER_LINE + LINE_BREAK).getBytes();
			outputStream.write(end_data);
		} finally {
			IOUtils.closeQuietly(fileInputStream);
		}
	}

	/**
	 * build body.
	 * @param fileName
	 * @return
	 */
	private String buildStartData(String fileName){
		StringBuilder bodyBuilder = new StringBuilder();
		bodyBuilder.append(CENTER_LINE)
				   .append(mBoundary)
				   .append(LINE_BREAK)
				   .append("Content-Disposition: form-data; name=\"img\"; filename=\""
						   + fileName + "\"" + "\r\n")
				   .append("Content-Type: application/octet-stream; charset="
						   + "utf-8" + LINE_BREAK)
				   .append(LINE_BREAK);
		return bodyBuilder.toString();
	}

	/**
	 * init header.
	 * @param httpURLConnection
	 */
	private void setHeader(HttpURLConnection httpURLConnection){
		httpURLConnection.setRequestProperty("Charset", "utf-8");
		httpURLConnection.setRequestProperty("connection", "keep-alive");
		httpURLConnection.setRequestProperty("Content-Type", CONTENT_TYPE
				+ ";boundary=" + mBoundary);
		Map<String,String> customHeader = mUploadRequest.getHeaderMap();
		if(customHeader != null && customHeader.isEmpty()){
			for (Map.Entry<String,String> entry : customHeader.entrySet()){
				httpURLConnection.setRequestProperty(entry.getKey(),entry.getValue());
			}
		}
	}
}